var LEFT = 0 ;
var RIGHT = 1 ;

var nextTabId = 1 ;

/**
 * @author David Milne
 */
var nextTabPaneId = 0 ;

function TabPane() {
	
	this.tabWidth ;
	this.canClose ;
	this.alignment ;
	
	this.tabs ;
	this.tabsTable ;
	this.tabsRow ;
	this.slideLeft ;
	this.slideRight ;
	this.currTabId ;
	this.tabIdLastRemoved ;
	
	this.selectionHandler ;
	this.num = nextTabPaneId ;
	nextTabPaneId ++ ;
}

TabPane.prototype.init = tabPane_init ;
TabPane.prototype.clear = tabPane_clear ;
TabPane.prototype.resize = tabPane_resize ;
TabPane.prototype.addTab = tabPane_addTab ;
TabPane.prototype.removeTab = tabPane_removeTab ;
TabPane.prototype.selectTab = tabPane_selectTab ;
TabPane.prototype.handleLayoutChange = tabPane_handleLayoutChange ;
TabPane.prototype.slide = tabPane_slide ;
TabPane.prototype.animateSlide = tabPane_animateSlide ;
TabPane.prototype.getTabIndexForId = tabPane_getTabIndexForId ;
TabPane.prototype.getTabIdForIndex = tabPane_getTabIdForIndex ;





function tabPane_init(selectionHandler, removalHandler, alignment, tabWidth) {
	try {
		this.canClose = (removalHandler != null) ;
		this.selectionHandler = selectionHandler ;
		this.removalHandler = removalHandler ;
		this.tabWidth = tabWidth ;	
		this.alignment = alignment ;	
				
		this.id = "TabPane" + this.num ;
		this.innerHTML = "" ;
		this.className = "tabPane" ;
		
		this.tabs = document.createElement("div") ;
		this.tabs.className = "tabs" ;
		this.appendChild(this.tabs) ;
		
		this.slideLeft = document.createElement("div") ;
		this.slideLeft.className = "left" ;
		this.slideLeft.onclick = new Function("getTabPane(" + this.num + ").slide(" + LEFT + ") ;") ;
		this.appendChild(this.slideLeft) ;
		
		this.slideRight = document.createElement("div") ;
		this.slideRight.className = "right" ;
		this.slideRight.onclick = new Function("getTabPane(" + this.num + ").slide(" + RIGHT + ") ;") ;
		this.appendChild(this.slideRight) ;
				
		this.clear() ;
		
	} catch ( e ) { 
		logError("tabPane.init.error: " + e ); 
		throw (e) ;
	}
} 

function tabPane_clear() {
	try {
		this.currTabId = -1 ;
		this.tabIdLastRemoved = -1 ;
		
		this.tabs.innerHTML = "" ;
		this.tabs.scrollLeft = 0 ;
		this.slideLeft.style.display = "none" ;
		this.slideRight.style.display = "none" ;
		
		this.tabsTable = document.createElement("table") ;
		if (this.alignment == RIGHT)
			this.tabsTable.style.cssFloat = "right" ;
		
		
		if (this.tabWidth != null) 
			this.tabsTable.style.width = "10px" ;
		
		this.tabs.appendChild(this.tabsTable) ;
		
		this.tabsRow = this.tabsTable.insertRow(0) ;				
	} catch ( e ) { 
		logError("tabPane.clear.error: " + e ); 
		throw (e) ;
	}		
}

function tabPane_resize(width) {
	
	this.style.width = width + "px" ;
	this.tabs.style.width = width - 40 + "px" ;
	this.handleLayoutChange() ;
}

function tabPane_addTab(content) {
	try {
		//var index = this.tabsRow.childNodes.length ;
		//logDebug("adding Tab: " + index + " - " + content) ;
		
		var tab = document.createElement("td") ;
		tab.id = "tab" + nextTabId ;
		
		
		tab.className = "tab_deselected" ;
		tab.innerHTML = content + "&nbsp;&nbsp<span></span>" ;
    	tab.onclick = new Function("getTabPane(" + this.num + ").selectTab(" + nextTabId + ") ;") ;
		
		if (this.canClose == true && this.tabWidth != null) {
			
			var mask = document.createElement("div") ;
			mask.className = "mask" ;
			mask.style.left = this.tabWidth - 29 + "px" ;
			tab.appendChild(mask) ;
			
			var closeTab = document.createElement("div") ;
			closeTab.className = "closeTab" ;
			closeTab.style.left = this.tabWidth - 25 + "px" ;
			closeTab.onclick = Function("getTabPane(" + this.num + ").removeTab(" + nextTabId + ") ;") ;
			tab.appendChild(closeTab) ;
		}
		
		if (this.tabWidth != null) {
			tab.style.width = this.tabWidth - 8 + "px" ;
		}
		
		this.tabsRow.appendChild(tab) ;
		nextTabId++ ;
		
		this.handleLayoutChange() ;
		
		
	} catch ( e ) { 
		logError("tabPane.addTab.error: " + e ); 
		throw (e) ;
	}
}

function tabPane_removeTab(tabId) {
	try {
		
		this.tabIdLastRemoved = tabId ;
		this.removalHandler.call() ;
		
		var tabIndex = this.getTabIndexForId(tabId) ;
		//logDebug("removing tab: " + tabIndex + " ta"
		
		currTabIndex = this.getTabIndexForId(this.currTabId) ;
		
		if (currTabIndex == tabIndex) {
			if (this.tabsRow.childNodes.length > 1){
				
				var oldTabIndex = currTabIndex ;
				this.currTabId = -1 ;
			
				this.selectionHandler.call() ;
			
				if (oldTabIndex == this.tabsRow.childNodes.length - 1) 
					this.selectTab(this.getTabIdForIndex(tabIndex - 1)) ;
				else
					this.selectTab(this.getTabIdForIndex(tabIndex + 1)) ;		
			} else {
				this.currTabId = -1 ;
			}
		}
		
		
		var tabToRemove = this.tabsRow.childNodes[tabIndex] ;
		this.tabsRow.removeChild(tabToRemove) ;
		
		
				
		this.handleLayoutChange() ;
	} catch ( e ) { 
		logError("tabPane.removeTab.error: " + e ); 
		throw (e) ;
	}
}

function tabPane_selectTab(tabId) {
	try {
		var tabIndex = this.getTabIndexForId(tabId) ;
		logDebug("select tabId:" + tabId + " tabIndex:" + tabIndex + " tabs:" + this.tabs.childNodes.length + " currTab:" + this.currTabId) ;
		
		currTabIndex = this.getTabIndexForId(this.currTabId) ;
		
		if (tabIndex == currTabIndex) 
   			return ;
		
		if (currTabIndex >= 0)
   			this.tabsRow.childNodes[currTabIndex].className = "tab_deselected" ;
   
  		this.currTabId = tabId ;
		var selectedTab = this.tabsRow.childNodes[tabIndex] ;
  		selectedTab.className = "tab_selected" ;
		
		if (selectedTab.style.visibility == "hidden") {
			this.slideLeft.style.display = "none" ;
			this.slideRight.style.display = "none" ;
			this.animateSlide(0, this.tabs.scrollLeft, selectedTab.offsetLeft) ;		
		}
		
		this.selectionHandler.call(tabIndex) ;
		
 	} catch (e) {
  		logError("tabPane.selectTab.error: " + e ); 
		throw (e) ;
	}
}



function tabPane_handleLayoutChange() {
	try {
	
		if (this.tabs.offsetWidth < this.tabs.scrollWidth) {
					
			var visibleStart = this.tabs.scrollLeft ;
			var visibleEnd = this.tabs.scrollLeft + this.tabs.offsetWidth ;
			
			//logDebug("visibleStart: " + visibleStart + ", visibleEnd: " + visibleEnd) ;
			
			var leftTab = null ;
			var rightTab = null ;
			var leftTabIndex = 0 ;
			var rightTabIndex = 0 ;
			
			for (var i=0 ; i<this.tabsRow.childNodes.length ; i++) {
				
				var tab = this.tabsRow.childNodes[i] ;
				
				//logDebug("tab start: " + tab.offsetLeft + " end: " + (tab.offsetLeft + tab.offsetWidth)) ;
				if (tab.offsetLeft >= visibleStart && (tab.offsetLeft + tab.offsetWidth) <= visibleEnd) {
					tab.style.visibility = "visible" ;
					
					if (leftTab==null) { 
						leftTab = tab ;
						leftTabIndex = i ;
					}
					
					rightTab = tab ; 
					rightTabIndex = i ;
				} else 
					tab.style.visibility = "hidden" ;
			}
						
			this.slideLeft.style.left = leftTab.offsetLeft - this.tabs.scrollLeft + "px" ;
			this.slideRight.style.left = rightTab.offsetLeft + rightTab.offsetWidth + 20 - this.tabs.scrollLeft + "px" ;
						
			if (this.tabs.scrollLeft > 0)
				this.slideLeft.style.display = "" ;
			else
				this.slideLeft.style.display = "none" ;
				
			if (this.tabs.scrollLeft + this.tabs.offsetWidth < this.tabs.scrollWidth)
				this.slideRight.style.display = "" ;
			else
				this.slideRight.style.display = "none" ;
			
			currTabIndex = this.getTabIndexForId(this.currTabId) ;
			
			if (currTabIndex >= 0) {	
				var currTab = this.tabsRow.childNodes[currTabIndex] ;
				if (currTab.style.visibility != "visible") {
					logDebug("current tab is hidden") ;
					if (currTab.offsetLeft < visibleStart && leftTabIndex >= 0) 
						this.selectTab(this.getTabIdForIndex(leftTabIndex)) ;
					else
						this.selectTab(this.getTabIdForIndex(rightTabIndex)) ;					
				}				
			}
		} else {
			this.slideLeft.style.display = "none" ;
			this.slideRight.style.display = "none" ;	
		}
	} catch ( e ) { 
		logError("tabPane.handleLayoutChange.error: " + e ); 
		throw (e) ;
	}	
}

function tabPane_slide(dir) {
	try {
		this.slideLeft.style.display = "none" ;
		this.slideRight.style.display = "none" ;
		
		var currOffset = this.tabs.scrollLeft ;
		var firstVisible = 0 ;
			
		for (var i=0 ; i<this.tabsRow.childNodes.length ; i++) {
				
			var tab = this.tabsRow.childNodes[i] ;
			if(tab.style.visibility == "visible") {
				firstVisible = i ;
				break ;
			}
		}
		
		if (dir == LEFT)
			this.animateSlide(0, this.tabs.scrollLeft, this.tabsRow.childNodes[firstVisible-1].offsetLeft) ;
		else
			this.animateSlide(0, this.tabs.scrollLeft, this.tabsRow.childNodes[firstVisible+1].offsetLeft) ;
	
	} catch ( e ) { 
		logError("tabPane.slide.error: " + e ); 
		throw (e) ;
	}		
}

function tabPane_animateSlide(x, startPos, endPos) {
	try {
		
		var posDiff = endPos - startPos ;
		if (Math.PI - x > 0.5) {
			
  			x = x + 0.5 ;
   			var y = (0.5 * (Math.sin(x-(Math.PI/2)))) + 0.5 ;
  
 	  		pos = Math.round(startPos + (y*posDiff)) ;
			//logDebug("sliding " + pos) ;
			
			this.tabs.scrollLeft = pos ;
			
			setTimeout("getTabPane(" + this.num + ").animateSlide(" + x + "," + startPos + "," + endPos + ")", 50) ;
		} else {
			this.tabs.scrollLeft = endPos ;
			this.handleLayoutChange() ;
		}
			
	} catch (e) {
		logError("tabPane.animateSlide.error: " + e) ;
		throw (e) ;
	}
}

function tabPane_getTabIndexForId(id) {
	try {
		
		for (var i=0 ; i<this.tabsRow.childNodes.length ; i++) {
			
			var tab = this.tabsRow.childNodes[i] ;
			if(tab.id == "tab" + id)
				return i ;
		}	
		
		return -1 ;
		
	} catch (e) {
		logError("tabPane.getTabIndexForId.error: " + e) ;
		throw (e) ;
	}
}

function tabPane_getTabIdForIndex(tabIndex) {
	try {
		
		var tab = this.tabsRow.childNodes[tabIndex] ;
		logDebug("getting id for index " + tabIndex + " - tabId:" + tab.id.substring(3) + " full:" + tab.id) ;
		
		return tab.id.substring(3) ;
		
	} catch (e) {
		logError("tabPane.getTabIdForIndex.error: " + e) ;
		throw (e) ;
	}	
	
}


function getTabPane(num) {
	try {
		var tabPane = document.getElementById("TabPane" + num) ; 
		return tabPane ; 
 	} catch (e) {
  		logError("getTabPane.error: " + e ); 
		throw (e) ;
	}
}
